package org.fastiot.protocol

import grails.databinding.BindUsing

class Command extends Packet {

    static enum Scene {
        Register(0), Cancelled(1), Login(2), Logout(3), Heartbeat(4), RemoteCtrl(9)
        final int value

        private Scene(int value) { this.value = value }

        static Scene byValue(int val) {
            values().find { it.value == val } ?:
                    { throw new IllegalArgumentException("Command\$Scene ${val} not found") }()
        }
    }

    static enum Behavior {
        Request(0), Response(1), ReqRespPair(9)
        final int value

        private Behavior(int value) { this.value = value }

        static Behavior byValue(int val) {
            values().find { it.value == val } ?:
                    { throw new IllegalArgumentException("Command\$Behavior ${val} not found") }()
        }
    }

    static enum Aging {
        Permanent(0), Temporary(1)
        final int value

        private Aging(int value) { this.value = value }

        static Aging byValue(int val) {
            values().find { it.value == val } ?:
                    { throw new IllegalArgumentException("Command\$Aging ${val} not found") }()
        }
    }

    String symbol

    @BindUsing({ obj, source ->
        Aging.byValue(Integer.parseInt(source["aging"] as String))
    })
    Aging aging

    @BindUsing({ obj, source ->
        Scene.byValue(Integer.parseInt(source["scene"] as String))
    })
    Scene scene

    @BindUsing({ obj, source ->
        Behavior.byValue(Integer.parseInt(source["behavior"] as String))
    })
    Behavior behavior

    String paramsDefinition
    Integer respondPacketCode
    String respondHexPacketCode

    static transients = ['respondHexPacketCode']

    static constraints = {
        symbol(blank: false, unique: true)
        aging(nullable: false, inList: Aging.values().toList())
        scene(nullable: false, unique: "behavior", inList: Scene.values().toList())
        behavior(nullable: false, inList: Behavior.values().toList())
        paramsDefinition(nullable: true, widget: 'textarea')
        respondPacketCode(nullable: true, min: 0)
    }

    static mapping = {
        table "packet_command"
        paramsDefinition type: "text"
    }

    def beforeValidate() {
        if(respondHexPacketCode && !respondPacketCode)
            respondPacketCode = Integer.parseInt(respondHexPacketCode, 16)
    }

    def afterLoad() {
        if (respondPacketCode)
            respondHexPacketCode = Integer.toHexString(respondPacketCode)
    }
}
